package com.atzly.community.datasource;


import cn.hutool.core.util.StrUtil;
import com.atzly.community.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 用来针对mysql路由的参数加载、监听
 */
@Slf4j
public class ZookeeperPropertiesLoader {
    private static ZookeeperService zookeeperService;

    private static Long appId;

    public static void setAppId(Long appId) {
        ZookeeperPropertiesLoader.appId = appId;
    }

    public static void setZookeeperService(ZookeeperService zookeeperService) {
        ZookeeperPropertiesLoader.zookeeperService = zookeeperService;
    }

    private static final String ROUTER_PATH = "/mysql/router/community";

    public static class INSTANCE {


        private static   Map<String, String> properties = new HashMap<>();

        public static Map<String, String> getProperties() {
            return properties;
        }

        public static void remove(String key) {
            properties.remove(key);
        }

        public static void putAll(Map<String, String> map) {
            properties.putAll(map);
        }
        public static boolean containsKey(String key) {
            return properties.containsKey(key);
        }
        public static void setProperties(Map<String, String> properties) {
            INSTANCE.properties = properties;
        }

        public static void setProperties(String key, String value) {
            INSTANCE.properties.put(key,value);
        }

        static {
            Map<String, String> list = zookeeperService.getList(ROUTER_PATH,null);
            INSTANCE.getProperties().putAll(list);
            Iterator<Map.Entry<String, String>> iterator = list.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> next = iterator.next();
                String key = next.getKey();
                boolean empty = INSTANCE.containsKey(key);
                if (!empty) {
                    INSTANCE.remove(key);
                }
                String path = ROUTER_PATH + "/" + key;
                Map<String, String> temp = zookeeperService.getList(path, key);
                INSTANCE.putAll(temp);
            }
            listenerChange();
        }

    }

    /**
     * 监听数据源配置
     */
    private static void listenerChange() {
        TreeCacheListener listener = new TreeCacheListener(){
            @Override
            public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent event) throws Exception {
                ChildData childData = event.getData();
                if (childData == null || childData.getData() == null) {
                    return;
                }
                String path = childData.getPath();
                String data = new String(event.getData().getData(), StandardCharsets.UTF_8);
                if (event.getType() == TreeCacheEvent.Type.NODE_ADDED) {
                    log.info("监听到新增数据库配置：【" + path + " : " + data + "】");
                    if (!StringUtils.isEmpty(path)) {
                        doRefresh(path,data);
                    }
                } else if (event.getType() == TreeCacheEvent.Type.NODE_UPDATED) {
                    log.info("监听到数据源配置修改：【" + path + " : " + data + "】");
                    if (!StringUtils.isEmpty(path)) {
                        doRefresh(path,data);
                    }
                }
            }
        };
        zookeeperService.addListener(ROUTER_PATH, listener);
    }

    public static void doRefresh(String path, String data) {
        path = path.replace(ROUTER_PATH + "/","");
        String currentPath = path.replace("/",".");
         if (currentPath.equals(DataSourceConfigManager.CURRENT_DB_ID)
                || currentPath.equals(String.format(DataSourceConfigManager.CURRENT_APP_DB_ID, appId))
        ) {
            // 初始化默认数据源
            INSTANCE.setProperties(currentPath, data);
            DataSourceConfigManager.zkProperties.putAll(INSTANCE.getProperties());
            return;
        }

        List<String> split = StrUtil.split(path, "/");

        // 判断是否是修改的数据源节点
        if (split.size() > 1  ) {
            String dbId = split.get(0);
            String configParam = split.get(1);

            INSTANCE.setProperties(StringUtil.contact(".", dbId, configParam), data);

            DynamicDataSource dynamicDataSource = SpringContextUtil.getBean("dataSource");
            dynamicDataSource.refreshDataSource(dbId);
        }
        DataSourceConfigManager.zkProperties.putAll(INSTANCE.getProperties());
    }
}
